//
// Created by admin on 2022-06-10.
//

#ifndef FFMPEGPLAYER_FFMPEG_H
#define FFMPEGPLAYER_FFMPEG_H

#include <jni.h>
#include <android/log.h>
#include <android/native_window.h>
#include <android/native_window_jni.h>
#define  LOG_TAG    "FFMPEG"
#define LOGI(FORMAT,...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,FORMAT,##__VA_ARGS__);
#define LOGE(FORMAT,...) __android_log_print(ANDROID_LOG_ERROR,"jason",FORMAT,##__VA_ARGS__);
#define SUCCESS 0
extern "C" {
#include "include/libavformat/avformat.h"
#include "include/libavcodec/avcodec.h"
#include "include/libswscale/swscale.h"
#include "include/libavutil/imgutils.h"
#include "include/libavutil/opt.h"
#include "include/libavdevice/avdevice.h"
}
enum State {
    STATE_INIT = 1,//初始化，将成员变量置位
    STATE_ALLOC_CONTEXT,//分配解复用器上下文
    STATE_OPEN_INPUT,//打开流
    STATE_FIND_STREAM_INFO,//获取视频信息
    STATE_FIND_VIDEO_INDEX,//找到视频帧
    STATE_AV_PIX_FMT_NONE,
    STATE_FIND_DECODER,//打开编码器
    STATE_AVCODEC_OPEN2,
    STATE_READ_FRAME,
    STATE_DECODE_VIDEO2,
    STATE_SET_BUFFERS_GEOMETRY,
    STATE_ANATIVE_WINDOW_LOCK,
    STATE_SWS_SCALE,
    STATE_END,
};
//模板函数
template <typename TYPE, void (TYPE::*_RunThread)() >
void* _thread_t(void* param)//线程启动函数，声明为模板函数
{
    TYPE* This = (TYPE*)param;
    This->openStream();
    return NULL;
}
class ffmpeg {
private:

    virtual ~ffmpeg();
    void logError(State state, char *msg);
    void logInfo(State state, char *msg);
    char buffer_log[1024];
    void logInfo(State state);
    void logError(State state);
    // 回调函数的参数，用了时间
    typedef struct {
        time_t lasttime;
        bool connected;
        int channel;
    } Runner;
    Runner input_runner;
    static int interrupt_callback(void *p);
    int connect();
    int prepareDecoder();
    void allocPacket();
    int decode();
    bool drawVideo();

    int video_index = -1;
    int audio_index = -1;

    SwsContext* swsContext = NULL;
    uint8_t  *out_buffer = NULL;
    AVPacket *packet = NULL;
    AVFrame *frame = NULL;
    AVFrame *rgb_frame = NULL;
    //视频编解码上下文
    AVCodecContext *avCodecContextVideo= NULL;
    AVCodecContext *avCodecContextAudio = NULL;
    AVCodec *avCodec = NULL;
    AVDictionary *avdic = NULL;
    AVFormatContext *avFormatContext = NULL;
    //视频缓冲区
    ANativeWindow_Buffer native_outBuffer;

    int readFrameError = 0;//读取数据错误次数

public:
    ffmpeg();
    static void init();
    void openStream();
    void reset();
    //释放内存
    void release();
    void openThread();
    void * download();


    int channel;//通道号对应数组下标
    jstring url;//流地址
    const char* pUrl = NULL;//流地址
    JNIEnv *env = NULL;
    jclass clazz = NULL;

    ANativeWindow *nativeWindow;
    volatile bool running = false;//是否被使用
    volatile bool bClose = false;//关闭流

    jobject callback;
};


#endif //FFMPEGPLAYER_FFMPEG_H
